﻿using System;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Globalization;
using System.Collections.Generic;

namespace HeroldIT.Dnn.JQuery
{
    /// <summary>
    /// Provides extension methods for <see cref="Page"/> objects.
    /// </summary>
    public static class PageExtensions
    {
        #region constants

        private static readonly string AddedStylesheetsKey = typeof (PageExtensions).FullName + "$AddedStylesheets";
        private static readonly string AddedConditionalStylesheetsKey = typeof(PageExtensions).FullName + "$AddedConditionalStylesheets";

        #endregion

        #region extension methods

        /// <summary>
        /// Adds a stylesheet reference with the given <paramref name="url"/> to the <paramref name="page"/>.
        /// </summary>
        /// <param name="page">The <see cref="Page"/> to add the stylesheet reference to.</param>
        /// <param name="url">The url of the stylesheet.</param>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Stylesheet")]
        public static void AddStylesheet(this Page page, string url)
        {
            if (null == page)
                throw new ArgumentNullException("page");
            if (String.IsNullOrEmpty(url))
                throw new ArgumentNullException("url");

            var uri = Uri.IsWellFormedUriString(url, UriKind.RelativeOrAbsolute)
                          ? new Uri(url, UriKind.RelativeOrAbsolute)
                          : new Uri(url);
            AddStylesheet(page, uri);
        }

        /// <summary>
        /// Adds a stylesheet reference with the given <paramref name="uri"/> to the <paramref name="page"/>.
        /// </summary>
        /// <param name="page">The <see cref="Page"/> to add the stylesheet reference to.</param>
        /// <param name="uri">The url of the stylesheet.</param>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Stylesheet")]
        public static void AddStylesheet(this Page page, Uri uri)
        {
            if (null == page)
                throw new ArgumentNullException("page");
            if (null == uri)
                throw new ArgumentNullException("uri");

            List<string> addedStylesheets = page.Items[AddedStylesheetsKey] as List<string>;
            if (null == addedStylesheets)
            {
                addedStylesheets = new List<string>();
                page.Items[AddedStylesheetsKey] = addedStylesheets;
            }
            string url = uri.ToString();
            if (!addedStylesheets.Contains(url))
            {
                addedStylesheets.Add(url);
                var link = new HtmlLink { Href = url };
                link.Attributes.Add("rel", "stylesheet");
                link.Attributes.Add("type", "text/css");
                page.Header.Controls.Add(link);
            }
        }

        /// <summary>
        /// Adds a conditional stylesheet reference with the given <paramref name="url"/> to the <paramref name="page"/>.
        /// </summary>
        /// <param name="page">The <see cref="Page"/> to add the stylesheet reference to.</param>
        /// <param name="condition">The condition for the comment block. Example: <c>lt IE 7</c></param>
        /// <param name="url">The url of the stylesheet.</param>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Stylesheet")]
        public static void AddConditionalStylesheet(this Page page, string condition, string url)
        {
            if (null == page)
                throw new ArgumentNullException("page");
            if (String.IsNullOrEmpty(condition))
                throw new ArgumentNullException("condition");
            if (String.IsNullOrEmpty(url))
                throw new ArgumentNullException("url");

            var uri = Uri.IsWellFormedUriString(url, UriKind.RelativeOrAbsolute) ? new Uri(url, UriKind.RelativeOrAbsolute) : new Uri(url);
            AddConditionalStylesheet(page, condition, uri);
        }

        /// <summary>
        /// Adds a conditional stylesheet reference with the given <paramref name="uri"/> to the <paramref name="page"/>.
        /// </summary>
        /// <param name="page">The <see cref="Page"/> to add the stylesheet reference to.</param>
        /// <param name="condition">The condition for the comment block. Example: <c>lt IE 7</c></param>
        /// <param name="uri">The url of the stylesheet.</param>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Stylesheet")]
        public static void AddConditionalStylesheet(this Page page, string condition, Uri uri)
        {
            if (null == page)
                throw new ArgumentNullException("page");
            if (String.IsNullOrEmpty(condition))
                throw new ArgumentNullException("condition");
            if (null == uri)
                throw new ArgumentNullException("uri");

            Dictionary<string, List<string>> addedConditionalStylesheets = page.Items[AddedConditionalStylesheetsKey] as Dictionary<string, List<string>>;
            if (null == addedConditionalStylesheets)
            {
                addedConditionalStylesheets = new Dictionary<string, List<string>>();
                page.Items[AddedConditionalStylesheetsKey] = addedConditionalStylesheets;
            }
            string url = uri.ToString();
            if (!addedConditionalStylesheets.ContainsKey(condition) || addedConditionalStylesheets[condition] == null)
            {
                addedConditionalStylesheets[condition] = new List<string>();
            }
            if (!addedConditionalStylesheets[condition].Contains(url))
            {
                addedConditionalStylesheets[condition].Add(url);
                var literal = new Literal
                                  {
                                      Text =
                                          String.Format(CultureInfo.InvariantCulture,
                                                        "<!--[if {0}]><link rel=\"stylesheet\" href=\"{1}\" type=\"text/css\" /><![endif]-->",
                                                        condition, uri)
                                  };
                page.Header.Controls.Add(literal);
            }
        }

        #endregion
    }
}